#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    createActions();
    createMenus();
    restore();
    createTabs();
    createToolBars();
    createStatusBar();
    setCurrentFile("");

    projectCreator = 0;
}

MainWindow::~MainWindow()
{
    delete ui;
    if(projectCreator) delete projectCreator;
    projectCreator = 0;
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    try
    {
        event->accept();
    }
    catch(exception &e)
    {
        qDebug() << e.what();
    }
}

void MainWindow::createActions()
{
    openAction = new QAction(tr("&New Project"), this);
    openAction->setShortcut(tr("Ctrl+N"));
    openAction->setIcon(QIcon("./icons/new.png"));
    openAction->setStatusTip(tr("Create project file, please select an image file!"));
    connect(openAction, SIGNAL(triggered()), this, SLOT(createProj()));

    openProjAction = new QAction(tr("&Open Project"), this);
    openProjAction->setShortcut(tr("Ctrl+O"));
    openProjAction->setIcon(QIcon("./icons/open.png"));
    openProjAction->setStatusTip(tr("Open a project file"));
    connect(openProjAction, SIGNAL(triggered()), this, SLOT(openProj()));

    saveAction = new QAction(tr("&Save"), this);
    saveAction->setShortcut(tr("Ctrl+S"));
    saveAction->setIcon(QIcon("./icons/save.png"));
    saveAction->setStatusTip(tr("Save an image file"));
    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));

    closeAction = new QAction(tr("Close Project"), this);
    connect(closeAction, SIGNAL(triggered()), this, SLOT(closeProj()));

    printAction = new QAction(tr("&Print"), this);
    printAction->setShortcut(tr("Ctrl+P"));
    connect(printAction, SIGNAL(triggered()), this, SLOT(print()));

    exitAction = new QAction(tr("&Exit"), this);
    exitAction->setShortcut(tr("Ctrl+E"));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));

    countAction = new QAction(tr("&Count Seeds"), this);
    countAction->setShortcut(tr("Ctrl+Alt+C"));
    connect(countAction, SIGNAL(triggered()), this, SLOT(count()));

    detectAction = new QAction(tr("&Detect Germination"), this);
    detectAction->setShortcut(tr("Ctrl+Alt+D"));
    connect(detectAction, SIGNAL(triggered()), this, SLOT(detect()));

    analyzeAction = new QAction(tr("&Analyze Seeds"), this);
    analyzeAction->setShortcut(tr("Ctrl+Alt+A"));
    connect(analyzeAction, SIGNAL(triggered()), this, SLOT(analyze()));

    aboutAction = new QAction(tr("&About this application"), this);
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));

    histAction = new QAction(tr("Histogram"), this);
    connect(histAction, SIGNAL(triggered()), this, SLOT(histgram()));

    pcaAction = new QAction(tr("PCA"), this);
    pcaAction->setShortcut(tr("Ctrl+Alt+P"));
    pcaAction->setStatusTip(tr("Principle Component Analysis"));
    connect(pcaAction, SIGNAL(triggered()), this, SLOT(doPCA()));
}

void MainWindow::createMenus()
{
    // File menu
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(openAction);
    fileMenu->addAction(openProjAction);
    fileMenu->addAction(saveAction);
    fileMenu->addAction(closeAction);
    fileMenu->addAction(printAction);
    fileMenu->addAction(exitAction);

    // Edit menu
    editMenu = menuBar()->addMenu(tr("&Edit"));

    // View menu
    viewMenu = menuBar()->addMenu(tr("&View"));
    viewMenu->addAction(histAction);

    // Tools menu
    toolsMenu = menuBar()->addMenu(tr("&Tools"));
    toolsMenu->addAction(analyzeAction);
    toolsMenu->addAction(countAction);
    toolsMenu->addAction(detectAction);
    toolsMenu->addAction(pcaAction);

    // Window menu
    windowMenu = menuBar()->addMenu(tr("&Window"));

    // Options menu
    optionsMenu = menuBar()->addMenu(tr("&Options"));

    // Help menu
    helpMenu = menuBar()->addMenu(tr("&Help"));
    helpMenu->addAction(aboutAction);
}

void MainWindow::createToolBars()
{
    newProj = new QToolButton(this);
    newProj->setText(tr(""));
    newProj->setIcon(QIcon("icons/new.png"));
    newProj->setToolTip("Create new project");
    ui->mainToolBar->addWidget(newProj);
    connect(newProj, SIGNAL(clicked()), this, SLOT(createProj()));

    open = new QToolButton(this);
    open->setText(tr(""));
    open->setIcon(QIcon("icons/open.png"));
    open->setToolTip("Open project");
    ui->mainToolBar->addWidget(open);
    connect(open, SIGNAL(clicked()), this, SLOT(openProj()));
}

void MainWindow::createTabs()
{
    countingTab = new CountingTab;
    detectionTab = new DetectionTab;
    analysisTab = new AnalysisTab;
    germTab = new GermTab;
    imgProcTab = new ImgProcTab;
    imgAcqTab = new ImgAcquisitionTab;

    ui->tabWidget->addTab(imgAcqTab, tr("Image Acquisition"));
    ui->tabWidget->addTab(detectionTab, tr("Experiment Data"));
    ui->tabWidget->addTab(countingTab, tr("Seed Count"));
    ui->tabWidget->addTab(analysisTab, tr("Shape Analysis"));
    ui->tabWidget->addTab(germTab, tr("Germination Analysis"));
    ui->tabWidget->addTab(imgProcTab, tr("Image Process"));

    connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(showTab(int)));
}

void MainWindow::createStatusBar()
{
    fileNameLabel = new QLabel(tr(""), statusBar());
    fileNameLabel->setAlignment(Qt::AlignHCenter);
    fileNameLabel->setMinimumSize(fileNameLabel->sizeHint());
    statusBar()->addWidget(fileNameLabel);
}

void MainWindow::updateStatusBar(const QString& curFile)
{
    fileNameLabel->setText(curFile);
}

void MainWindow::setCurrentFile(const QString &fileName)
{
    curFile = fileName;
}

// Based on selected image file, create a project file
void MainWindow::createProj()
{    
    if(detectionTab->isProjOpened())
    {
        closeProj();
    }

    informationControl = new InformationControl;
    connect(informationControl, SIGNAL(finished(int)), this, SLOT(inputDone(int)));
    informationControl->show();
}

void MainWindow::inputDone(int result)
{
    if(result == 1 && informationControl)
    {
        if(projectCreator == 0)
            projectCreator = new ProjectCreator(informationControl->getFile(),
                                            informationControl->getDir(),
                                            informationControl->getStartDateTime(),
                                            informationControl->getInterval(),
                                            informationControl->isIncluded());

        pop(projectCreator->getExpFile());

    }
    else
    {
        ui->statusBar->showMessage("A project has not been created!!!  ", 3000);
    }
}

void MainWindow::showTab(int tab)
{
    if(tab == 0)
        imgAcqTab->showContent();
    else if(tab == 1)
        detectionTab->showContent();
    else if(tab == 2)
        countingTab->showContent();
    else if(tab == 3)
        analysisTab->showContent();
    else if(tab == 4)
        germTab->showContent();
    else if(tab == 5)
        imgProcTab->showContent();
}

void MainWindow::openProj()
{
    if(detectionTab->isProjOpened())
    {
        int ans = QMessageBox::warning(this, tr("Open Project"),
                                       tr("A project file has been opened, do you still want to open "
                                          "a new project ?"), QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes);

        switch (ans){
            case QMessageBox::Cancel : return; break;
            case QMessageBox::Yes : close(); break;
            case QMessageBox::No : return; break;
            default : break;
        }
    }
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Project file"), "/home",
                                                    tr("Project Files (*.sgf)"));

    pop(fileName);

}

// When a project file is loaded, populate all
// tabs with image loader
void MainWindow::pop(const QString& fileName)
{
    if(!fileName.isEmpty() && fileName.contains(".sgf"))
    {
        // DetectionTab is used to open project file
        // 'fileName' is the name of the project file
        detectionTab->populate(fileName);
        connect(detectionTab->getLoader(), SIGNAL(imageSelected(QString)), this, SLOT(updateStatusBar(QString)));

        countingTab->addLoader(detectionTab->getLoader());
        analysisTab->addLoader(detectionTab->getLoader());
        germTab->addLoader(detectionTab->getLoader());
        imgProcTab->addLoader(detectionTab->getLoader());
        imgAcqTab->addLoader(detectionTab->getLoader());

        ui->tabWidget->setCurrentIndex(1);
    }
    else
    {
        ui->statusBar->showMessage("Please select a project file  ", 3000);
    }
}

bool MainWindow::save()
{
    bool isSaved = false;
    QString imageName = QFileDialog::getSaveFileName(this, tr("Save result image file"), "/home",
                                                     tr("Image file (*.jpg *.png *.bmp"));
    isSaved = detectionTab->saveImage(imageName);

    if(isSaved)
    {
        saveFile(imageName);
    }
    else return false;

    return true;
}

bool MainWindow::closeProj()
{
    restore();
    createTabs();
    return true;
}

bool MainWindow::saveFile(const QString &fileName)
{
    // Write File
    setCurrentFile(fileName);
    statusBar()->showMessage(tr("File saved"), 3000);
    return true;
}

void MainWindow::histgram()
{
    detectionTab->drawHistogram();
}

void MainWindow::doPCA()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open file for Principle Component Analysis"), "/home",
                                                    tr("PCA file (*.csv)"));

    QFile file(fileName);
    if(file.open(QIODevice::ReadOnly))
    {
        QTextStream in(&file);
        QStringList list;
        vector<Mat> inputVect;
        int rows, cols;

        while(!in.atEnd())
        {
            list = in.readLine().simplified().split(",");

            cols = list.size() ;
            Mat rowMat(1, cols, CV_64FC1);

            for(int j = 0; j < cols; j++)
            {
                rowMat.at<double>(0, j) = list.at(j).toDouble();
            }

            inputVect.push_back(rowMat);
        }

        rows = inputVect.size();
        Mat inputMat(rows, cols, CV_64FC1);

        for(int i = 0; i < rows; i++)
        {
            Mat row = inputVect.at(i);

            for(int j = 0; j < cols; j++ )
                inputMat.at<double>(i, j) = row.at<double>(0, j);
        }

        PCA pca(inputMat, Mat(), CV_PCA_DATA_AS_ROW, cols - 4);

        Mat compress(rows, cols-4, inputMat.type());
        Mat recons(rows, cols, inputMat.type());

        pca.project(inputMat, compress);
        pca.backProject(compress, recons);

        qDebug() << pca.eigenvalues.rows <<  " eigenvalue " << pca.eigenvalues.cols;
        qDebug() << pca.eigenvectors.rows <<  " eigenVector " << pca.eigenvectors.cols;
        qDebug() << compress.rows <<  " dimension " << compress.cols;


        inputVect.clear();
        file.close();
    }
}

void MainWindow::print()
{


}

void MainWindow::about()
{
    QMessageBox::about(this, tr("About Application"),
                 tr("This application explore image texture analysis methods "
                    "to create project file, open project file and count seeds, "
                    "also this application several algorithm to detect seed germination."));
}

void MainWindow::count()
{
    ui->tabWidget->setCurrentIndex(1);
}

void MainWindow::detect()
{
    ui->tabWidget->setCurrentIndex(3);
}

void MainWindow::analyze()
{
    ui->tabWidget->setCurrentIndex(2);
}

void MainWindow::restore()
{
    ui->tabWidget->clear();
}
